package XML与JSON.使用DOM4J;

import java.io.IOException;
//import java.io.File;
import java.io.InputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/*
使用Xpath需要Maven增加以下依赖
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>2.0.0</version>
</dependency>
 */
/*解析 XML 文档
使用 DOM4J 的步骤
以下是使用 DOM4J Parser 解析文档时使用的步骤。

1.导入 XML 相关的包。
2.创建一个 SAXReader。  创建解析器对象  SAXReader saxReader=new SAXReader();
3.从文件或流创建文档。  使用解析器对象读取XML文档生成Document对象
  Document document = saxReader.read(Dom4jParseUserXmlTest.class.getClassLoader().getResource("users.xml"));
	根据Document对象获取XML的元素（标签）信息:
	Dom4j的常用API说明:

	方法	                                    操作
	Element getRootElement();	               获取XML文件的根节点
	String getName();	                        返回标签的名称
	List < Element > elements();	            获取标签所有的子标签
	String arrtributeVallue(String name) ;	   获取指定属性名称的属性值
	String getText();	获取标签的文本
	String elementText(String name);	         获取指定名称的子标签的文本，返回子标签文本的值
	
4.通过调用 document.selectNodes() 使用 XPath 表达式获取所需节点
	【Dom4j提供基于XPath的API】
			方法																			操作
	Node selectSingleNode(String xpathExpression);			根据XPath表达式获取单个标签(元素/节点)
	List < Node > selectNodes(String xpathExpression)		根据XPath表达式获取多个标签(元素/节点)
   
   【XPath的语法】
	绝对路径表示方式：
	以/开头的路径表示绝对路径，绝对路径是从根元素开始写。例如 /元素/子元素/子子元素……；
	相对路径的表达方式：
	相对于当前节点的元素继续查找的节点，不以/开头，…/表示上一个元素，./表示当前元素；
	全文搜索路径方式：
	例如//子元素，//子元素//子子元素，//子元素/子子元素。
	注意：
	//表示无论中间有多少层，直接获取所有子元素所有满足条件的元素
	/表示只找一层
	谓语（条件筛选形式）
	例如 ： //元素[@attr1=value]


5.提取根元素。
6.遍历节点列表。
7.检查属性。
8.检查子元素。

导入 XML 相关的包
import java.io.*;
import java.util.*;
import org.dom4j.*;
 
创建一个 DocumentBuilder
SAXBuilder saxBuilder = new SAXBuilder();
 
从文件或流创建文档
File inputFile = new File("input.txt");
SAXBuilder saxBuilder = new SAXBuilder();
Document document = saxBuilder.build(inputFile);
 
提取根元素
Element classElement = document.getRootElement();
 
检查属性
//returns specific attribute
valueOf("@attributeName"); 
 
检查子元素
//returns first child node
selectSingleNode("subelementName"); 
 
演示示例
这里是我们需要解析的输入xml文件 −

<?xml version = "1.0"?>
<class>
   <student rollno = "393">
      <firstname>dinkar</firstname>
      <lastname>kad</lastname>
      <nickname>dinkar</nickname>
      <marks>85</marks>
   </student>
   
   <student rollno = "493">
      <firstname>Vaneet</firstname>
      <lastname>Gupta</lastname>
      <nickname>vinni</nickname>
      <marks>95</marks>
   </student>
   
   <student rollno = "593">
      <firstname>jasvir</firstname>
      <lastname>singn</lastname>
      <nickname>jazz</nickname>
      <marks>90</marks>
   </student>
</class>
*/
public class DOM4J解析XML {

   public static void main(String[] args) throws IOException {

      try {
      	SAXReader reader = new SAXReader();
         //File inputFile = new File("src\\main\\java\\XML与JSON\\使用DOM4J\\input.xml");
      	//Document document = reader.read(inputFile);
         InputStream input = DOM4J解析XML.class.getResourceAsStream("input.txt");
         Document document = reader.read(input);

         System.out.println("Root element :" + document.getRootElement().getName());

         Element classElement = document.getRootElement();

         List<Node> nodes = document.selectNodes("/class/student");
         System.out.println("----------------------------");
         
         for (Node node : nodes) {
            System.out.println("\nCurrent Element :"+ node.getName());
            System.out.println("Student roll no : " + node.valueOf("@rollno") );
            System.out.println("First Name : " + node.selectSingleNode("firstname").getText());
            System.out.println("Last Name : " + node.selectSingleNode("lastname").getText());
            System.out.println("First Name : " + node.selectSingleNode("nickname").getText());
            System.out.println("Marks : " + node.selectSingleNode("marks").getText());
         }
         
         List<Element> SubElementList = classElement.elements();
         for (Element SumElement:SubElementList) {
         	System.out.println("\nCurrent Element :"+ SumElement.getName());
         }
       //拿到第一个学生的marks
         System.out.println("1.------>使用绝对路径方式来查找元素");
         Element element = (Element) document.selectSingleNode("/class/student/marks");
         String marks = element.getText();
         System.out.println(marks);

         System.out.println("2.------>使用相对路径查找元素");
         //element是当前获取的marks元素  ..:选取当前节点的父节点
         Element name = (Element) element.selectSingleNode("../firstname");//"/class/student/marks"为当前路径
         System.out.println("第一个用户的姓名为"+name.getText());

         System.out.println("3.------>使用全局搜索的方式");
         //获取所有的lastname元素的文本
         List<Node> idNodeList = document.selectNodes("//lastname");
         for (Node node : idNodeList) {
             Element idElement=(Element) node;
             System.out.println(idElement.getText());
          }
         System.out.println("4.------>谓语形式");
         //获取rollno = "493"的用户信息
         Element idElement = (Element) document.selectSingleNode("//student[@rollno = \'493\']");
         List<Element> elements = idElement.elements();
         for (Element element1 : elements) {
             System.out.println(element1.getName()+"="+element1.getText());
         }
         
         //将原文件输出至控制台 1.createPrettyPrint()：完美型多行输出  2.createCompactFormat()：紧凑型一行输出
         OutputFormat format = OutputFormat.createPrettyPrint();//完美型多行输出，多行显示
         XMLWriter writer = new XMLWriter( System.out, format );
         writer.write( document );
         
      } catch (DocumentException e) {
         e.printStackTrace();
      }
      
   }
}
/* 
这将产生以下结果 −

Root element :class
----------------------------

Current Element :student
Student roll no : 393
First Name : dinkar
Last Name : kad
First Name : dinkar
Marks : 85

Current Element :student
Student roll no : 493
First Name : Vaneet
Last Name : Gupta
First Name : vinni
Marks : 95

Current Element :student
Student roll no : 593
First Name : jasvir
Last Name : singn
First Name : jazz
Marks : 90

Current Element :student

Current Element :student

Current Element :student
1.------>使用绝对路径方式来查找元素
85
2.------>使用相对路径查找元素
第一个用户的姓名为dinkar
3.------>使用全局搜索的方式
kad
Gupta
singn
4.------>谓语形式
firstname=Vaneet
lastname=Gupta
nickname=vinni
marks=95
*/